package com.jade.gateway.init;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.cloud.nacos.NacosConfigProperties;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.nacos.api.NacosFactory;
import com.alibaba.nacos.api.PropertyKeyConst;
import com.alibaba.nacos.api.config.ConfigService;
import com.alibaba.nacos.api.config.listener.Listener;
import com.alibaba.nacos.api.exception.NacosException;
import com.jade.gateway.constants.RouterConstant;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;
import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Properties;
import java.util.concurrent.Executor;

/**
 * @author Arnold
 * @version V2.0
 * @className GateWayApplication
 * @description 动态路由初始化类
 * @date 2021/12/30 09:56
 **/
@Slf4j
@Configuration
@RequiredArgsConstructor
public class DynamicRouteInit {

    /**
     * 路由定义写入器
     */
    private final RouteDefinitionWriter routeDefinitionWriter;

    /**
     * nacos 配置
     */
    private final NacosConfigProperties nacosProperties;

    @PostConstruct
    public void initRoute() {
        try {
            Properties properties = new Properties();
            properties.put(PropertyKeyConst.SERVER_ADDR, nacosProperties.getServerAddr());
            properties.put(PropertyKeyConst.USERNAME, nacosProperties.getUsername());
            properties.put(PropertyKeyConst.PASSWORD, nacosProperties.getPassword());
            properties.put(PropertyKeyConst.NAMESPACE, nacosProperties.getNamespace());
            //nacos 配置接口
            ConfigService configService = NacosFactory.createConfigService(properties);
            //获取配置
            String content = configService.getConfig(RouterConstant.CONFIG_DATA_ID_DYNAMIC_ROUTES, nacosProperties.getGroup(), RouterConstant.CONFIG_TIMEOUT_MS);
            updateRoute(content);
            //开户监听，实现动态
            configService.addListener(RouterConstant.CONFIG_DATA_ID_DYNAMIC_ROUTES, nacosProperties.getGroup(), new Listener() {
                @Override
                public void receiveConfigInfo(String configInfo) {
                    updateRoute(configInfo);
                }

                @Override
                public Executor getExecutor() {
                    return null;
                }
            });
        } catch (NacosException e) {
            log.error("加载路由出错：{}", e.getErrMsg());
        }
    }

    /**
     *  更新（新增）路由
     * @param content 路由信息
     * @return void
     * @author Arnold
     * @date 2022/4/11
     **/
    public void updateRoute(String content) {
        log.info("初始化网关路由开始...");
        List<RouteDefinition> gatewayRouteList = JSONArray.parseArray(content, RouteDefinition.class);
        if (CollUtil.isNotEmpty(gatewayRouteList)) {
            gatewayRouteList.forEach(routeDefinition ->
            {
                log.info("加载路由：{}", routeDefinition);
                routeDefinitionWriter.save(Mono.just(routeDefinition)).subscribe();
            });
        }
        log.info("更新网关路由完成");
    }

}
